package com.dalei.vdserver.webservice;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.jws.WebService;

import com.dalei.vdserver.dao.ImagesDao;
import com.dalei.vdserver.dao.InvalidItemsDao;
import com.dalei.vdserver.dao.LogDao;
import com.dalei.vdserver.dao.TaskDao;
import com.dalei.vdserver.dao.VehicleInformationDao;
import com.dalei.vdserver.model.DetectionResult;
import com.dalei.vdserver.model.DetectionTask;
import com.dalei.vdserver.model.ErrorCode;
import com.dalei.vdserver.model.Images;
import com.dalei.vdserver.model.InvalidItems;
import com.dalei.vdserver.model.Log;
import com.dalei.vdserver.model.Task;
import com.dalei.vdserver.model.VehicleInformation;
import com.dalei.vdserver.util.StringChecksum;
import com.google.gson.Gson;

@WebService(endpointInterface = "com.dalei.vdserver.webservice.DetectionService")
public class DetectionServiceImpl implements DetectionService {

	private TaskDao taskDao;

	private VehicleInformationDao vehicleInformationDao;

	private LogDao logDao;

	private InvalidItemsDao invalidItemsDao;

	private ImagesDao imagesDao;

	public TaskDao getTaskDao() {
		return taskDao;
	}

	public void setTaskDao(TaskDao taskDao) {
		this.taskDao = taskDao;
	}

	public VehicleInformationDao getVehicleInformationDao() {
		return vehicleInformationDao;
	}

	public void setVehicleInformationDao(
			VehicleInformationDao vehicleInformationDao) {
		this.vehicleInformationDao = vehicleInformationDao;
	}

	public LogDao getLogDao() {
		return logDao;
	}

	public void setLogDao(LogDao logDao) {
		this.logDao = logDao;
	}

	public InvalidItemsDao getInvalidItemsDao() {
		return invalidItemsDao;
	}

	public void setInvalidItemsDao(InvalidItemsDao invalidItemsDao) {
		this.invalidItemsDao = invalidItemsDao;
	}

	public ImagesDao getImagesDao() {
		return imagesDao;
	}

	public void setImagesDao(ImagesDao imagesDao) {
		this.imagesDao = imagesDao;
	}

	@Override
	public String getDetectionTasks(int deviceId) {
		// TODO Auto-generated method stub
		List<DetectionTask> detectionTasks = new ArrayList<DetectionTask>();
		List<Task> tasks = taskDao.getTasksByDeviceId(deviceId);
		if (tasks != null) {
			for (Task task : tasks) {
				DetectionTask detectionTask = new DetectionTask();
				detectionTask.setFid(task.getFid());
				VehicleInformation vehicleInformation = vehicleInformationDao
						.getVehicleInformation(task.getVehicleInformationId());
				if (vehicleInformation != null) {
					detectionTask.setLicensePlateNumber(vehicleInformation
							.getLicensePlateNumber());
				} else {
					detectionTask.setLicensePlateNumber(null);
				}
				detectionTask.setTimestamp(task.getTimestamp());
				detectionTasks.add(detectionTask);
			}
		}
		Gson gson = new Gson();
		return gson.toJson(detectionTasks, List.class);
	}

	@Override
	public int lockDetectionTask(int fid) {
		// TODO Auto-generated method stub
		Task task = taskDao.getTaskById(fid);
		if (task != null) {
			if (task.isLocked() == false) {
				task.setLocked(true);
				int rowAffected = taskDao.updateTask(task);
				if (rowAffected > 0) {
					return fid;
				} else if (rowAffected == -1) {
					return ErrorCode.INTERNAL_ERROR;
				} else {
					return ErrorCode.UNKNOW_ERROR;
				}
			} else {
				return ErrorCode.Detection.TASK_ALREADY_LOCKED;
			}
		} else {
			return ErrorCode.Detection.GET_TASK_FAILED;
		}
	}

	@Override
	public int unlockDetectionTask(int fid) {
		// TODO Auto-generated method stub
		Task task = taskDao.getTaskById(fid);
		if (task != null) {
			if (task.isLocked()) {
				task.setLocked(false);
				int rowAffected = taskDao.updateTask(task);
				if (rowAffected > 0) {
					return fid;
				} else if (rowAffected == -1) {
					return ErrorCode.INTERNAL_ERROR;
				} else {
					return ErrorCode.UNKNOW_ERROR;
				}
			} else {
				return ErrorCode.Detection.TASK_ALREADY_UNLOCKED;
			}
		} else {
			return ErrorCode.Detection.GET_TASK_FAILED;
		}
	}
	
	@Override
	public String getVehicleInformation(int fid) {
		// TODO Auto-generated method stub
		VehicleInformation vi = vehicleInformationDao
				.getVehicleInformationOfTask(fid);
		Gson gson = new Gson();
		return gson.toJson(vi, VehicleInformation.class);
	}
	
	@Override
	public int saveDetectionResult(String json, long crc32) {
		// TODO Auto-generated method stub
		if (json != null) {
			if (StringChecksum.verifyChecksum(json, crc32)) {
				Gson gson = new Gson();
				DetectionResult dr = gson.fromJson(json, DetectionResult.class);
				if (dr != null) {
					int fid = dr.getFid();
					List<Integer> invalidItemsList = dr.getInvalidItems();
					if (invalidItemsList != null) {
						Map<Integer, byte[]> imagesMap = dr.getImages();
						if (imagesMap != null) {
							Task t = taskDao.getTaskById(fid);
							if (t != null) {
								int s = 0;

								int vehicleInformationId = t
										.getVehicleInformationId();
								int deviceId = dr.getDeviceId();
								int userId = dr.getUserId();
								int odometerReading = dr.getOdometerReading();
								String notes = dr.getNotes();
								Date timeStamp = dr.getTimeStamp();

								Log log = new Log();
								log.setFid(fid);
								log.setVehicleInformationId(vehicleInformationId);
								log.setDeviceId(deviceId);
								log.setUserId(userId);
								log.setOdometerReading(odometerReading);
								log.setNotes(notes);
								log.setTimeStamp(timeStamp);
								int ra = logDao.saveLog(log);
								if (ra > 0) {
									s = s + ra;
									int[] raArray = null;

									InvalidItems invalidItems = new InvalidItems();
									invalidItems.setFid(fid);
									invalidItems
											.setInvalidItems(invalidItemsList);
									raArray = invalidItemsDao
											.addInvalidItems(invalidItems);
									for (int i : raArray) {
										s = s + i;
										if (i == 0) {
											invalidItemsDao
													.clearInvalidItems(fid);
											logDao.clearLog(fid);
											return ErrorCode.Detection.SAVE_INVALID_ITEMS_FAILED;
										}
									}

									Images images = new Images();
									images.setFid(fid);
									images.setImages(imagesMap);
									raArray = imagesDao.addImages(images);
									for (int i : raArray) {
										s = s + i;
										if (i == 0) {
											imagesDao.clearImages(fid);
											invalidItemsDao
													.clearInvalidItems(fid);
											logDao.clearLog(fid);
											return ErrorCode.Detection.SAVE_IMAGES_FAILED;
										}
									}
									
									ra = taskDao.removeTask(fid);
									s = s + ra;
									return s;
								} else {
									return ErrorCode.Detection.SAVE_LOG_FAILED;
								}
							} else {
								return ErrorCode.Detection.GET_TASK_FAILED;
							}
						} else {
							return ErrorCode.Detection.NULL_IMAGES_MAP;
						}
					} else {
						return ErrorCode.Detection.NULL_INVALID_ITEMS_LIST;
					}
				} else {
					return ErrorCode.Detection.NULL_DETECTIONRESULT;
				}
			} else {
				return ErrorCode.Detection.CHECKSUM_ERROR;
			}
		} else {
			return ErrorCode.Detection.NULL_JSON;
		}
	}
}
